package co.fitstart.weapp.api.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.utils.DateUtils;

import co.fitstart.entity.course.ResultReport;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.CourseRoundResult;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.user.StudentTargetData;
import co.fitstart.entity.user.bwh.BwhRecord;
import co.fitstart.entity.user.inbody.InbodyRecord;
import co.fitstart.weapp.api.dao.BwhRecordDao;
import co.fitstart.weapp.api.dao.CourseRoundDao;
import co.fitstart.weapp.api.dao.CourseRoundResultDao;
import co.fitstart.weapp.api.dao.CourseScheduleDao;
import co.fitstart.weapp.api.dao.InbodyDao;
import co.fitstart.weapp.api.dao.StudentTargetDao;
import co.fitstart.weapp.api.entity.CourseAchievement;
import co.fitstart.weapp.api.handler.ImageHandler;
import co.fitstart.weapp.api.service.CourseAchievementService;

/**
 * 
 * @author haiyan_xiao
 *
 */
@Service("courseAchievementService")
public class CourseAchievementServiceImpl implements CourseAchievementService {

//    private Logger logger = LoggerFactory.getLogger(CourseAchievementServiceImpl.class);
//
//    private static final String GENERATE_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
//
//    private static final String ACHIEVEMTNT_PAGE = "pages/user-course/user-course-detail/achievement-index/achievement-index";

    @Value("#{config['access_token_url']}")
    private String accessTokenUrl;

    @Value("#{config['file.upload.path']}")
    private String fileUploadPath;

    @Value("#{config['achievement.qrcode.path']}")
    private String achievementQrcodePath;

    @Dao
    private CourseScheduleDao courseScheduleDao;

    @Dao
    private StudentTargetDao studentTargetDao;

    @Dao
    private InbodyDao inbodyDao;

    @Dao
    private BwhRecordDao bwhRecordDao;

    @Dao
    private CourseRoundDao courseRoundDao;

    @Dao
    private CourseRoundResultDao courseRoundResultDao;

    @Autowired
    private ImageHandler imageHandler;

    @Autowired
    private GenericDaoSupport genericDaoSupport;

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.CourseAchievementService#getCourseAchievement(co.fitstart.entity.course.round.CourseRound)
     */
    public CourseAchievement getCourseAchievement(CourseRound courseRound) {
        String name = null;
        String avatar = null;
        if(courseRound.getStudent().getUser().getProfile() != null) {
            name = courseRound.getStudent().getUser().getProfile().getNickname();
            avatar = courseRound.getStudent().getUser().getProfile().getAvatar();
        }
        
        List<CourseSchedule> courseSchedules = courseScheduleDao.list(courseRound, ScheduleStatus.FINISH);
        Date firstScheduleDate = courseSchedules.isEmpty() ? null : courseSchedules.get(courseSchedules.size() - 1).getOccurDate();
        
        StudentTargetData studentTargetData = studentTargetDao.load(courseRound);
        
        Date effectiveStart = courseRound.getEffectiveStart() != null ? courseRound.getEffectiveStart() : new Date();
        Date effectiveEnd = courseRound.getEffectiveEnd() != null ? courseRound.getEffectiveEnd() : courseRound.calculateEffectiveEnd(effectiveStart);
        long effectiveDay = (effectiveEnd.getTime() - effectiveStart.getTime())/1000/60/60/24;
        
        InbodyRecord startInbody = null;
        InbodyRecord endInbody = null;
        if(!courseSchedules.isEmpty()) {
            List<InbodyRecord> inbodyRecords = inbodyDao.list(courseRound.getStudent().getUser(), DateUtils.parseDate(DateFormatUtils.format(firstScheduleDate, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss"), DateUtils.parseDate(DateFormatUtils.format(courseSchedules.get(0).getOccurDate(), "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
            
            if(!inbodyRecords.isEmpty()) {
                startInbody = inbodyRecords.get(0);
                endInbody = inbodyRecords.get(inbodyRecords.size() - 1);
            }
        }
        
        String startPhoto = null;
        Date startUploadTime = null;
        String endPhoto = null;
        Date endUploadTime = null;
        CourseRoundResult result = courseRoundResultDao.load(courseRound);
        if(result != null) {
            startPhoto = result.getPreviousPicture();
            startUploadTime = result.getPreviousUploadTime();
            endPhoto = result.getLaterPicture();
            endUploadTime = result.getLaterUploadTime();
        }
        if(startPhoto == null && endPhoto == null) {
            ResultReport resultReport = courseRoundDao.loadResultReport(courseRound);
            
            if(resultReport != null) {
                startPhoto = resultReport.getPreviousPicture();
                endPhoto = resultReport.getLatterPicture();
            }
        }
        BwhRecord startBwh = null;
        BwhRecord endBwh = null;
        List<BwhRecord> bwhRecords = bwhRecordDao.list(courseRound);
        if(!bwhRecords.isEmpty()) {
            startBwh = bwhRecords.get(0);
            endBwh = bwhRecords.get(bwhRecords.size() - 1);
        }
        
        return new CourseAchievement(name, avatar, courseRound.getFinished(), firstScheduleDate, studentTargetData, effectiveDay,
                startInbody, endInbody, startPhoto, startUploadTime, endPhoto, endUploadTime, startBwh, endBwh);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.CourseAchievementService#getCourseAchievementShare(co.fitstart.entity.course.round.CourseRound)
     */
    public Map<String, Object> getCourseAchievementShare(CourseRound courseRound) {
        Map<String, Object> result = new HashMap<>();
        
//        if(courseRound.getAchievementQrcode() == null) {
//            this.generateQrcode(courseRound);
//        }
//        
//        result.put("qrcode", courseRound.getAchievementQrcode());
        result.put("finished", courseRound.getFinished());
        
        Date effectiveStart = courseRound.getEffectiveStart() != null ? courseRound.getEffectiveStart() : new Date();
        Date effectiveEnd = courseRound.getEffectiveEnd() != null ? courseRound.getEffectiveEnd() : courseRound.calculateEffectiveEnd(effectiveStart);
        result.put("effective_start", DateFormatUtils.format(effectiveStart, "yyyy.MM.dd"));
        result.put("effective_end", DateFormatUtils.format(effectiveEnd, "yyyy.MM.dd"));
        
        StudentTargetData studentTargetData = studentTargetDao.load(courseRound);
        if(studentTargetData != null) {
            result.put("digital", studentTargetData.getTargetType().isDigital());
            
            long effectiveDay = (effectiveEnd.getTime() - effectiveStart.getTime())/1000/60/60/24;
            
            if(studentTargetData.getTargetType().isDigital()) {
                result.put("target_type", studentTargetData.getTargetType());
                result.put("target", "目标：" + effectiveDay + "天" + studentTargetData.getTarget());
                
                List<CourseSchedule> courseSchedules = courseScheduleDao.list(courseRound, ScheduleStatus.FINISH);
                
                if(courseSchedules.size() >= 1) {
                    List<InbodyRecord> inbodyRecords = inbodyDao.list(courseRound.getStudent().getUser(), DateUtils.parseDate(DateFormatUtils.format(courseSchedules.get(courseSchedules.size() - 1).getOccurDate(), "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss"), DateUtils.parseDate(DateFormatUtils.format(courseSchedules.get(0).getOccurDate(), "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
                    
                    if(inbodyRecords.size() > 1) {
                        InbodyRecord startInbody = inbodyRecords.get(0);
                        InbodyRecord endInbody = inbodyRecords.get(inbodyRecords.size() - 1);
                        
                        if(studentTargetData.getTargetType().isBodyFatRateReducing()) {
                            BigDecimal bfrChange;
                            if(startInbody.getBfr() > endInbody.getBfr()) {
                                bfrChange = new BigDecimal((startInbody.getBfr() - endInbody.getBfr()) * 100).setScale(1, RoundingMode.HALF_UP);
                            } else {
                                bfrChange = new BigDecimal(0);
                            }
                            
                            if(studentTargetData.getWeightChange() == null || studentTargetData.getWeightChange() == 0) {
                                result.put("change_desc", "减脂" + bfrChange + "%");
                                result.put("bfr_change_value", bfrChange);
                            } else {
                                BigDecimal weightChange;
                                if(startInbody.getWeight() > endInbody.getWeight()) {
                                    weightChange = new BigDecimal(startInbody.getWeight() - endInbody.getWeight()).setScale(1, RoundingMode.HALF_UP);
                                } else {
                                    weightChange = new BigDecimal(0);
                                }
                                
                                result.put("change_desc", "减脂" + bfrChange + "%,减重" + weightChange + "KG");
                                result.put("bfr_change_value", bfrChange);
                                result.put("weight_change_value", weightChange);
                            }
                        } else if(studentTargetData.getTargetType().isWeightLosing()) {
                            BigDecimal weightChange;
                            
                            if(startInbody.getWeight() > endInbody.getWeight()) {
                                weightChange = new BigDecimal(startInbody.getWeight() - endInbody.getWeight()).setScale(1, RoundingMode.HALF_UP);
                            } else {
                                weightChange = new BigDecimal(0);
                            }
                            
                            result.put("change_desc", "减重" + weightChange + "KG");
                            result.put("weight_change_value", weightChange);
                        } else {
                            BigDecimal bfrChange;
                            BigDecimal weightChange;
                            
                            if(startInbody.getBfr() > endInbody.getBfr()) {
                                bfrChange = new BigDecimal((startInbody.getBfr() - endInbody.getBfr()) * 100).setScale(1, RoundingMode.HALF_UP);
                            } else {
                                bfrChange = new BigDecimal(0);
                            }
                            
                            if(startInbody.getWeight() < endInbody.getWeight()) {
                                weightChange = new BigDecimal(endInbody.getWeight() - startInbody.getWeight()).setScale(1, RoundingMode.HALF_UP);
                            } else {
                                weightChange = new BigDecimal(0);
                            }
                            
                            result.put("change_desc", "减脂" + bfrChange + "%,增重" + weightChange + "KG");
                            result.put("bfr_change_value", bfrChange);
                            result.put("weight_change_value", weightChange);
                        }
                    } else {
                        if(studentTargetData.getTargetType().isBodyFatRateReducing()) {
                            if(studentTargetData.getWeightChange() == null || studentTargetData.getWeightChange() == 0) {
                                result.put("change_desc", "减脂0%");
                                result.put("bfr_change_value", 0);
                            } else {
                                result.put("change_desc", "减脂0%,减重0KG");
                                result.put("bfr_change_value", 0);
                                result.put("weight_change_value", 0);
                            }
                        } else if(studentTargetData.getTargetType().isWeightLosing()) {
                            result.put("change_desc", "减重0KG");
                            result.put("weight_change_value", 0);
                        } else {
                            result.put("change_desc", "减脂0%,增重0KG");
                            result.put("bfr_change_value", 0);
                            result.put("weight_change_value", 0);
                        }
                    }
                } else {
                    if(studentTargetData.getTargetType().isBodyFatRateReducing()) {
                        if(studentTargetData.getWeightChange() == null || studentTargetData.getWeightChange() == 0) {
                            result.put("change_desc", "减脂0%");
                            result.put("bfr_change_value", 0);
                        } else {
                            result.put("change_desc", "减脂0%,减重0KG");
                            result.put("bfr_change_value", 0);
                            result.put("weight_change_value", 0);
                        }
                    } else if(studentTargetData.getTargetType().isWeightLosing()) {
                        result.put("change_desc", "减重0KG");
                        result.put("weight_change_value", 0);
                    } else {
                        result.put("change_desc", "减脂0%,增重0KG");
                        result.put("bfr_change_value", 0);
                        result.put("weight_change_value", 0);
                    }
                }
            } else {
                result.put("target_description", studentTargetData.getTargetType().isPosture() ? "调整体态" : "收获健康");
                result.put("target_description_detail", studentTargetData.getDescription());
                result.put("target", "目标：" + studentTargetData.getTargetType().getDescription());
            }
        }
        
        return result;
    }

    public Map<String, Object> uploadContrastPhoto(CourseRound courseRound, MultipartFile photo, String suffix) {
        CourseRoundResult courseRoundResult = courseRoundResultDao.load(courseRound);
        
        String imageName;
        
        if(courseRoundResult == null) {
            imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" +suffix;
        } else {
            if("before".equals(suffix)) {
                if(courseRoundResult.getPreviousPicture() == null) {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix;
                } else if(courseRoundResult.getPreviousVersion() == null) {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix + "_1";
                } else {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix + "_" + (courseRoundResult.getPreviousVersion() + 1);
                }
            } else {
                if(courseRoundResult.getLaterPicture() == null) {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix;
                } else if(courseRoundResult.getLaterVersion() == null) {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix + "_1";
                } else {
                    imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + suffix + "_" + (courseRoundResult.getLaterVersion() + 1);
                }
            }
        }
        
        String path = imageHandler.upload(photo, imageName);
        
        if(courseRoundResult == null) {
            courseRoundResult = new CourseRoundResult(courseRound, path, suffix);
            genericDaoSupport.save(courseRoundResult);
        } else {
            genericDaoSupport.update(courseRoundResult.editPicture(path, suffix));
        }
        
        Map<String, Object> result = new HashMap<>();
        
        result.put("src", path);
        result.put("uploadTime", "before".equals(suffix) ? courseRoundResult.getPreviousUploadTime() : courseRoundResult.getLaterUploadTime());
        
        return result;
    }

//    private void generateQrcode(CourseRound courseRound) {
//        try {
//            Response accessTokenResponse = Request.Get(accessTokenUrl)
//                                                  .connectTimeout(100000)
//                                                  .socketTimeout(100000)
//                                                  .execute();
//            
//            String accessTokenBody = accessTokenResponse.returnContent().asString(Consts.UTF_8);
//            
//            System.out.println(accessTokenBody);
//            
//            HttpResult accessTokenResult = JSON.parseObject(accessTokenBody, HttpResult.class);
//            
//            if(accessTokenResult.isValid()) {
//                Map<String, String> parameters = new HashMap<>();
//                parameters.put("scene", "" + courseRound.getId());
//                parameters.put("page", ACHIEVEMTNT_PAGE);
//                String content = JsonUtils.toJsonString(parameters);
//                
//                Response response = Request.Post(GENERATE_QRCODE_URL + accessTokenResult.getData().get("access_token"))
//                                           .bodyString(content, ContentType.APPLICATION_JSON)
//                                           .connectTimeout(100000)
//                                           .socketTimeout(100000)
//                                           .execute();
//                
//                HttpEntity entity = response.returnResponse().getEntity();
//                if(IOUtils.toString(entity.getContent(), "utf-8").startsWith("{\"errcode\":")) {
//                    logger.error("request for qrcode error(): [{}]", IOUtils.toString(entity.getContent(), "utf-8"));
//                    throw new BusinessException("生成二维码失败");
//                } else {
//                    String imageName = (courseRound.getCode() == null ? "" : courseRound.getCode()) + "_" + courseRound.getId() + ".jpg";
//                    File file = new File(fileUploadPath + achievementQrcodePath, imageName);
//                    
//                    // 2. 将字节流copy到新文件
//                    try {
//                        FileUtils.copyInputStreamToFile(entity.getContent(), file);
//                        
//                        genericDaoSupport.update(courseRound.editAchievementQrcode(achievementQrcodePath + "/" + imageName));
//                    } catch (IOException e) {
//                        logger.error("save qrcode error(): [{}]", e);
//                        throw new BusinessException("生成二维码失败");
//                    }
//                }
//            } else {
//                logger.error("request for access token error(): [{}]", accessTokenResult.getMessage());
//                throw new BusinessException("生成二维码失败");
//            }
//        } catch (IOException e) {
//            logger.error("request for access token error(): [{}]", e);
//            throw new BusinessException("生成二维码失败");
//        }
//    }
}
